package com.boot.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.boot.annotation.RateLimit;
import com.boot.constants.RedisKeys;
import com.boot.constants.StatusConstants;
import com.boot.entity.Comment;
import com.boot.entity.Question;
import com.boot.entity.User;
import com.boot.service.ICommentService;
import com.boot.service.IQuestionService;
import com.boot.service.IUserService;
import com.boot.service.MailService;
import com.boot.utils.R;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/api/comments")
@Slf4j
public class CommentController {

    @Resource
    private ICommentService commentService;

    @Resource
    private IUserService userService;

    @Resource
    private MailService mailService;

    @Resource
    private IQuestionService questionService;

    @Resource(name = "stringRedisTemplate")
    private StringRedisTemplate redisTemplate;

    /**
     * 获取某问题下的所有已通过评论
     */
    @GetMapping("/question/{questionId}")
    @RateLimit(limit = 20, windowSec = 60)
    public R<List<CommentDTO>> getComments(@PathVariable Long questionId) {
        try {
            List<Comment> comments = commentService.getApprovedCommentsByQuestionId(questionId);
            List<CommentDTO> dtos = comments.stream().map(this::convertToDTO).collect(Collectors.toList());
            return R.success(dtos);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return R.error("系统错误");
        }
    }

    // ========== DTO & 转换方法 ==========
    private CommentDTO convertToDTO(Comment comment) {
        CommentDTO dto = new CommentDTO();
        dto.setId(comment.getId());
        dto.setQuestionId(comment.getQuestionId());
        dto.setUserId(comment.getUserId());
        dto.setContent(comment.getContent());
        dto.setStatus(comment.getStatus());
        dto.setCreatedAt(comment.getCreatedAt());
        dto.setUsername(comment.getUsername());
        return dto;
    }

    @Data
    public static class CommentDTO {
        private Long id;
        private Long questionId;
        private Long userId;
        private String username; // 前端需要用户名
        private String content;
        private String status;
        private LocalDateTime createdAt;

        public String getCreatedAt() {
            return this.createdAt != null ? this.createdAt.toString() : "";
        }
    }

    /**
     * 评论通过：将评论状态改为 approved
     */
    @PostMapping("/{id}/approve")
    @RateLimit(limit = 10, windowSec = 60)
    public R<Void> approveComment(@PathVariable Long id) {
        Comment comment = commentService.getById(id);
        if (comment == null) {
            return R.error("评论不存在");
        }

        // 查询用户信息
        User user = userService.getById(comment.getUserId());
        if (user == null || user.getEmail() == null || user.getEmail().trim().isEmpty()) {
            log.warn("无法发送邮件：用户 {} 不存在或邮箱为空", comment.getUserId());
            return R.error("用户不存在或邮箱为空");
        }

        if (user.getStatus().equals(StatusConstants.UserStatus.DISABLED)) {
            return R.error("无法发送邮件：用户已被禁用");
        }

        // 获取问题标题（需要 service 支持）
        String questionTitle = "未知问题";
        try {
            Question question = questionService.getById(comment.getQuestionId());
            questionTitle = question != null ? question.getTitle() : "未知问题";
        } catch (Exception e) {
            log.warn("无法获取问题标题，ID: {}", comment.getQuestionId(), e);
        }

        UpdateWrapper<Comment> wrapper = new UpdateWrapper<>();
        wrapper.eq("id", id)
                .set("status", StatusConstants.CommentStatus.APPROVED)
                .set("updated_at", LocalDateTime.now());

        boolean updated = commentService.update(wrapper);

        if (updated && user.getEmail() != null && !user.getEmail().trim().isEmpty()) {
            try {
                String subject = "您的评论已通过审核";
                String content = buildApprovedEmail(user.getUsername(), questionTitle, comment.getContent());
                mailService.sendHtmlMail(user.getEmail(), subject, content);

                // 已处理，去除redis中记录的评论
                redisTemplate.opsForSet().remove(RedisKeys.SENT_COMMENT_NOTIFY, String.valueOf(id));
            } catch (Exception e) {
                log.error("【邮件发送失败】评论通过通知: " + user.getEmail() + ", 错误: " + e.getMessage(), e);
            }
        }

        if (updated) {
            // 审批通过后，减少对应用户的待审批评论计数
            decrementPendingCount(comment.getUserId(), comment.getQuestionId());
        }

        return updated ? R.success(null) : R.error("操作失败");
    }

    /**
     * 减少待审批评论计数
     */
    private void decrementPendingCount(Long userId, Long questionId) {
        String redisKey = "comment:pending:" + userId + ":" + questionId;
        redisTemplate.opsForValue().decrement(redisKey);
    }

    /**
     * 评论驳回：将评论状态改为 rejected
     */
    @PostMapping("/{id}/reject")
    @RateLimit(limit = 10, windowSec = 60)
    public R<Void> rejectComment(@PathVariable Long id) {
        Comment comment = commentService.getById(id);
        if (comment == null) {
            return R.error("评论不存在");
        }

        User user = userService.getById(comment.getUserId());
        if (user == null || user.getEmail() == null || user.getEmail().trim().isEmpty()) {
            log.warn("无法发送邮件：用户 {} 不存在或邮箱为空", comment.getUserId());
            return R.error("用户不存在或邮箱为空");
        }

        if (user.getStatus().equals(StatusConstants.UserStatus.DISABLED)) {
            return R.error("无法发送邮件：用户已被禁用");
        }

        // 获取问题标题（需要 service 支持）
        String questionTitle = "未知问题";
        try {
            Question question = questionService.getById(comment.getQuestionId());
            questionTitle = question != null ? question.getTitle() : "未知问题";
        } catch (Exception e) {
            log.warn("无法获取问题标题，ID: {}", comment.getQuestionId(), e);
        }

        UpdateWrapper<Comment> wrapper = new UpdateWrapper<>();
        wrapper.eq("id", id)
                .set("status", StatusConstants.CommentStatus.REJECTED)
                .set("updated_at", LocalDateTime.now());

        boolean updated = commentService.update(wrapper);

        if (updated && user.getEmail() != null && !user.getEmail().trim().isEmpty()) {
            try {
                String subject = "您的评论未通过审核";
                String content = buildRejectedEmail(user.getUsername(), questionTitle, comment.getContent());
                mailService.sendHtmlMail(user.getEmail(), subject, content);

                // 已处理，去除redis中记录的评论
                redisTemplate.opsForSet().remove(RedisKeys.SENT_COMMENT_NOTIFY, String.valueOf(id));
            } catch (Exception e) {
                log.error("【邮件发送失败】评论驳回通知: " + user.getEmail() + ", 错误: " + e.getMessage(), e);
            }
        }

        if (updated) {
            // 驳回后，减少对应用户的待审批评论计数
            decrementPendingCount(comment.getUserId(), comment.getQuestionId());
        }

        return updated ? R.success(null) : R.error("操作失败");
    }

    /**
     * 评论禁用：将已通过的评论下架（设为 disabled）
     */
    @PostMapping("/{id}/disable")
    @RateLimit(limit = 10, windowSec = 60)
    public R<Void> disableComment(@PathVariable Long id) {
        Comment comment = commentService.getById(id);
        if (comment == null) {
            return R.error("评论不存在");
        }

        User user = userService.getById(comment.getUserId());
        if (user == null || user.getEmail() == null || user.getEmail().trim().isEmpty()) {
            log.warn("无法发送邮件：用户 {} 不存在或邮箱为空", comment.getUserId());
            return R.error("用户不存在或邮箱为空");
        }

        if (user.getStatus().equals(StatusConstants.UserStatus.DISABLED)) {
            return R.error("无法发送邮件：用户已被禁用");
        }

        // 获取问题标题（需要 service 支持）
        String questionTitle = "未知问题";
        try {
            Question question = questionService.getById(comment.getQuestionId());
            questionTitle = question != null ? question.getTitle() : "未知问题";
        } catch (Exception e) {
            log.warn("无法获取问题标题，ID: {}", comment.getQuestionId(), e);
        }

        UpdateWrapper<Comment> wrapper = new UpdateWrapper<>();
        wrapper.eq("id", id)
                .set("status", StatusConstants.CommentStatus.DISABLED)
                .set("updated_at", LocalDateTime.now());

        boolean updated = commentService.update(wrapper);

        if (updated && user.getEmail() != null && !user.getEmail().trim().isEmpty()) {
            try {
                String subject = "您的评论已被下架";
                String content = buildDisabledEmail(user.getUsername(), questionTitle, comment.getContent());
                mailService.sendHtmlMail(user.getEmail(), subject, content);

                // 已处理，去除redis中记录的评论
                redisTemplate.opsForSet().remove(RedisKeys.SENT_COMMENT_NOTIFY, String.valueOf(id));
            } catch (Exception e) {
                log.error("【邮件发送失败】评论禁用通知: " + user.getEmail() + ", 错误: " + e.getMessage(), e);
            }
        }

        return updated ? R.success(null) : R.error("操作失败");
    }

    @RateLimit(limit = 20, windowSec = 60)
    // 查询所有待审批的评论（分页）
    @GetMapping("/pending-review")
    public R<IPage<Comment>> getPendingReviewComments(
            @RequestParam(defaultValue = "1") Integer pageNum,
            @RequestParam(defaultValue = "10") Integer pageSize) {

        Page<Comment> page = new Page<>(pageNum, pageSize);
        QueryWrapper<Comment> wrapper = new QueryWrapper<Comment>()
                .in("status", StatusConstants.CommentStatus.PENDING)
                .orderByDesc("created_at"); // 按创建时间倒序

        IPage<Comment> result = commentService.page(page, wrapper);

        List<Comment> comments = result.getRecords();
        // 获取所有评论者的 ID
        List<Long> userIds = comments.stream()
                .map(Comment::getUserId)
                .distinct()
                .collect(Collectors.toList());

        if (userIds.size() > 0) {
            // 查询用户名
            QueryWrapper<User> userWrapper = new QueryWrapper<>();
            userWrapper.in("id", userIds).select("id", "username");
            List<User> users = userService.list(userWrapper);

            Map<Long, String> usernameMap = users.stream()
                    .collect(Collectors.toMap(User::getId, User::getUsername));

            // 填充用户名
            comments.forEach(c -> c.setUsername(usernameMap.getOrDefault(c.getUserId(), "未知用户")));
        }

        return R.page(result);
    }

    private String buildApprovedEmail(String username, String questionTitle, String commentContent) {
        return "<div style='font-family: Arial, sans-serif; padding: 20px; border: 1px solid #ddd; border-radius: 8px; max-width: 600px; margin: auto;'>"
                    + "<h2 style='color: #4CAF50;'>✅ 您的评论已通过审核</h2>"
                    + "<p><strong>尊敬的 " + username + "：</strong></p>"
                    + "<p>您在问题 <em>“" + escapeHtml(questionTitle) + "”</em> 下发表的以下评论已通过审核，并已公开显示：</p>"
                    + "<blockquote style='background: #f9f9f9; border-left: 5px solid #ccc; padding: 10px 15px; margin: 15px 0; font-style: italic;'>"
                        + escapeHtml(commentContent)
                    + "</blockquote>"
                    + "<p>感谢您的参与与支持！</p>"
                    + "<footer style='margin-top: 30px; color: #777; font-size: 0.9em; text-align: center;'>"
                    + "&copy; " + java.time.LocalDate.now().getYear() + " 系统管理平台</footer>"
                + "</div>";
    }

    private String buildRejectedEmail(String username, String questionTitle, String commentContent) {
        return "<div style='font-family: Arial, sans-serif; padding: 20px; border: 1px solid #ddd; border-radius: 8px; max-width: 600px; margin: auto;'>"
                    + "<h2 style='color: #f44336;'>❌ 您的评论未通过审核</h2>"
                    + "<p><strong>尊敬的 " + username + "：</strong></p>"
                    + "<p>很抱歉，您在问题 <em>“" + escapeHtml(questionTitle) + "”</em> 下发表的以下评论未通过审核，已被驳回：</p>"
                    + "<blockquote style='background: #f9f9f9; border-left: 5px solid #ccc; padding: 10px 15px; margin: 15px 0; font-style: italic;'>"
                        + escapeHtml(commentContent)
                    + "</blockquote>"
                    + "<p>如有疑问，请联系系统管理员。</p>"
                    + "<footer style='margin-top: 30px; color: #777; font-size: 0.9em; text-align: center;'>"
                    + "&copy; " + java.time.LocalDate.now().getYear() + " 系统管理平台</footer>"
                + "</div>";
    }

    private String buildDisabledEmail(String username, String questionTitle, String commentContent) {
        return "<div style='font-family: Arial, sans-serif; padding: 20px; border: 1px solid #ddd; border-radius: 8px; max-width: 600px; margin: auto;'>"
                    + "<h2 style='color: #FF9800;'>⚠️ 您的评论已被下架</h2>"
                    + "<p><strong>尊敬的 " + username + "：</strong></p>"
                    + "<p>您在问题 <em>“" + escapeHtml(questionTitle) + "”</em> 下发表的以下评论因内容不符合规范，已被管理员下架（禁用）：</p>"
                    + "<blockquote style='background: #f9f9f9; border-left: 5px solid #ccc; padding: 10px 15px; margin: 15px 0; font-style: italic;'>"
                        + escapeHtml(commentContent)
                    + "</blockquote>"
                    + "<p>请遵守社区准则，避免发布违规内容。</p>"
                    + "<footer style='margin-top: 30px; color: #777; font-size: 0.9em; text-align: center;'>"
                    + "&copy; " + java.time.LocalDate.now().getYear() + " 系统管理平台</footer>"
                + "</div>";
    }

    private String escapeHtml(String str) {
        if (str == null) return "";
        return str.replace("&", "&amp;")
                .replace("<", "&lt;")
                .replace(">", "&gt;")
                .replace("\"", "&quot;")
                .replace("'", "&#x27;");
    }
}
